#include "MainFrame.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

unsigned char* Img8To24(unsigned char* i, long size)
{
	unsigned char* res = (unsigned char*)malloc(size * 3);
	unsigned char* ptr1 = &res[0];
	for(long s=0;s<size;s++)
	{
		*ptr1 = i[s];
		ptr1++;
		*ptr1 = i[s];
		ptr1++;
		*ptr1 = i[s];
		ptr1++;
	}
	return res;
}

MainFrame::MainFrame() :
    wxFrame(nullptr,wxID_ANY,wxT("灰度重心"))
{
    HandleList=new wxListCtrl(this,(int)MainFrameID::HandleList,wxDefaultPosition,wxDefaultSize,wxLC_REPORT);
    btnExeImageList=new wxButton(this,(int)MainFrameID::btnExeImageList,wxT("处理图片序列"));
    spinAreaX=new wxSpinCtrl(this,(int)MainFrameID::spinAreaX);
    spinAreaY=new wxSpinCtrl(this,(int)MainFrameID::spinAreaY);
    btnFilter=new wxButton(this,(int)MainFrameID::btnFilter,wxT("过滤图片"));
    spinThreshold=new wxSpinCtrl(this,(int)MainFrameID::spinThreshold);
    btnExecute=new wxButton(this,(int)MainFrameID::btnExecute,wxT("开始执行"));
    imageDisplay=new ImageDisplay(this);
    imageList=new wxListCtrl(this,(int)MainFrameID::imageList,wxDefaultPosition,wxDefaultSize,wxLC_REPORT);
    filePicker=new wxFilePickerCtrl(this,(int)MainFrameID::filePicker,wxEmptyString,wxT(""),wxT(""),wxDefaultPosition,wxDefaultSize,wxFLP_OPEN);
    wxSizer* mainSizer=new wxBoxSizer(wxVERTICAL);
    wxSizer* subSizer=new wxBoxSizer(wxHORIZONTAL);
    wxSizer* bSizer=new wxBoxSizer(wxVERTICAL);
    bSizer->Add(imageList,wxSizerFlags().Proportion(8).Expand());
    bSizer->Add(HandleList,wxSizerFlags().Proportion(8).Expand());
    bSizer->Add(spinAreaX,wxSizerFlags().Proportion(1).Expand());
    bSizer->Add(spinAreaY,wxSizerFlags().Proportion(1).Expand());
    bSizer->Add(spinThreshold,wxSizerFlags().Proportion(1).Expand());
    bSizer->Add(btnFilter,wxSizerFlags().Proportion(1).Expand());
    bSizer->Add(btnExecute,wxSizerFlags().Proportion(1).Expand());
    bSizer->Add(btnExeImageList,wxSizerFlags().Proportion(1).Expand());
    subSizer->Add(bSizer,wxSizerFlags().Proportion(2).Expand());
    subSizer->AddSpacer(5);
    subSizer->Add(imageDisplay,wxSizerFlags().Proportion(6).Expand());
    mainSizer->Add(filePicker,wxSizerFlags().Proportion(1).Expand());
    mainSizer->Add(subSizer,wxSizerFlags().Proportion(10).Expand());
    SetSizerAndFit(mainSizer);
    imageList->SetMaxSize(wxSize(300,10000));
    HandleList->SetMaxSize(wxSize(300,10000));
    Bind(wxEVT_BUTTON,&MainFrame::on_btnExeImageList_click,this,(int)MainFrameID::btnExeImageList);
    Bind(wxEVT_SPINCTRL,&MainFrame::on_spinHandleArea_change,this,(int)MainFrameID::spinAreaX);
    Bind(wxEVT_SPINCTRL,&MainFrame::on_spinHandleArea_change,this,(int)MainFrameID::spinAreaY);
    Bind(wxEVT_BUTTON,&MainFrame::on_btnFilter_click,this,(int)MainFrameID::btnFilter);
    Bind(wxEVT_LIST_ITEM_SELECTED,&MainFrame::on_imageList_select,this,(int)MainFrameID::imageList);
    Bind(wxEVT_BUTTON,&MainFrame::on_btnExecute_click,this,(int)MainFrameID::btnExecute);
    Bind(wxEVT_FILEPICKER_CHANGED,&MainFrame::on_filePicker_change,this,(int)MainFrameID::filePicker);

    spinThreshold->SetRange(0,254);
}

MainFrame::~MainFrame()
{

}

void MainFrame::on_btnExeImageList_click(wxCommandEvent& event)
{
    wxProgressDialog dialog(wxT("处理中"),wxT("正在处理图像"),imageNumber,this);
    wxPointList pl;long InsertColumnCount=0;
    HandleList->ClearAll();
    HandleList->AppendColumn(wxT("加入处理的图片"));
    
    long Threshold=spinThreshold->GetValue();
    long emptyImage=0,handleImage=0;
    unsigned char* imgData;
    uint64_t timesp;
    for(int i=0;i<imageNumber;i++)
    {
        if(!dialog.Update(i))
            return;
        try
        {
            selectImage(i);
            GetImageData(&imgData,&timesp);
            wxPoint* p=new wxPoint(imageDisplay->GetGrayCenter(imgData,Threshold));
            pl.Append(p);
        }
        catch(const int& e)
        {
            emptyImage++;
            continue;
        }
        HandleList->InsertItem(InsertColumnCount,wxString()<<i+1);
        InsertColumnCount++;
        delete [] imgData;
    }
    imageDisplay->LinkPoints(pl);
    wxMessageBox(wxString()<<wxT("已排除文件数: ")<<emptyImage,wxT("处理结果"));
}

void MainFrame::on_spinHandleArea_change(wxSpinEvent& event)
{
    imageDisplay->SetHandleArea(spinAreaX->GetValue(),spinAreaY->GetValue());
}

void MainFrame::on_btnExecute_click(wxCommandEvent& event)
{
    imageDisplay->HandleImage(spinThreshold->GetValue());
}

void MainFrame::OpenBMPFile(std::string path)
{
    int x,y,n;

    unsigned char* data=stbi_load(path.c_str(),&x,&y,&n,1);
    spinAreaX->SetRange(0,x);
    spinAreaY->SetRange(0,y);
    spinAreaX->SetValue(x);
    spinAreaY->SetValue(y);
    if(data==nullptr)
    {
        wxMessageBox(wxT("文件打开失败"),wxT("操作异常"));
        return;
    }
    imageHeight=y;
    imageWidth=x;
    switch (n)
    {
    case 1:
        imageDisplay->SetImage(Img8To24(data,imageHeight*imageWidth),imageHeight,imageWidth);
        break;
    
    case 3:
        {
            wxImage img;
            img.LoadFile(path,wxBITMAP_TYPE_BMP);
            imageDisplay->SetImage(img);
        }
        break;

    default:
        wxMessageBox(wxT("图像通道数异常"),wxT("数据异常"));
        break;
    }
    imageDisplay->SetHandleArea(x,y);
    stbi_image_free(data);
}

void MainFrame::OpenCCSFile(std::string path)
{
    if(targetFile.is_open())
        targetFile.close();
    targetFile.open(path,std::ios_base::binary | std::ios_base::in);
    if(!targetFile.is_open())
    {
        wxMessageBox(wxT("文件打开失败"),wxT("操作异常"));
        return;
    }
    targetFile.seekg(0,std::ios_base::beg);
    targetFile.read((char*)&imageNumber,sizeof(imageNumber));
    targetFile.read((char*)&imageWidth,sizeof(imageWidth));
    targetFile.read((char*)&imageHeight,sizeof(imageHeight));
    imageList->AppendColumn(wxT("图像序号"));
    for(int i=1;i<=imageNumber;i++)
    {
        imageList->InsertItem(i-1,wxString()<<i);
    }
    spinAreaX->SetRange(0,imageWidth);
    spinAreaY->SetRange(0,imageHeight);
    spinAreaX->SetValue(imageWidth);
    spinAreaY->SetValue(imageHeight);
    imageDisplay->SetHandleArea(imageWidth,imageHeight);
}

void MainFrame::on_filePicker_change(wxFileDirPickerEvent& event)
{
    std::string path=filePicker->GetPath().ToStdString();
    if(path.length()==0)
    {
        wxMessageBox("文件路径为空");
        return;
    }
    std::string fileSuffix=path.substr(path.find_last_of('.')+1);
    imageList->ClearAll();
    if(fileSuffix=="ccs")
    {
        fileType=FileType::ccs;
        OpenCCSFile(path);
    }
    else if(fileSuffix=="bmp")
    {
        fileType=FileType::bmp;
        OpenBMPFile(path);
    }
    else
    {
        wxMessageBox(wxT("不受支持的文件类型"),wxT("操作错误"));
        return;
    }
}

void MainFrame::selectImage(long index)
{
    targetFile.seekg(headOffset+(imageWidth*imageHeight+8)*index,std::ios::beg);
}

void MainFrame::GetImageData(unsigned char** imageData,uint64_t* timesp)
{
    unsigned char* res=new unsigned char[imageWidth*imageHeight];
    targetFile.read((char*)timesp,sizeof(uint64_t));
    targetFile.read((char*)res,imageWidth*imageHeight);
    *imageData=res;
}

void MainFrame::on_imageList_select(wxListEvent& event)
{
    long index=event.GetIndex();
    selectImage(index);
    unsigned char* imageData;
    uint64_t timesp;
    GetImageData(&imageData,&timesp);
    imageDisplay->SetImage(Img8To24(imageData,imageHeight*imageWidth),imageHeight,imageWidth);
    delete[] imageData;
}

void MainFrame::on_btnFilter_click(wxCommandEvent& event)
{
    imageDisplay->FilterImage(spinThreshold->GetValue());
}